home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1997 August / Walnut Creek CDROM.7z / VOL_400 / 466_01 / SRC / TOPICLOG.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1996-12-20  |  10.7 KB  |  626 lines

  1. #include <afx.h>
  2. #include <afxtempl.h>
  3. #include "parse.h"
  4. #include "topiclog.h"
  5. #include "errmsg.h"
  6.  
  7. /**************************************************************************
  8.  Tag Class
  9.  **************************************************************************/
  10.  
  11. CTag::CTag(void)
  12. {
  13.     nFields = 0;
  14.     ZeroMem(aszFieldText, sizeof(char *)*MAXNUMFIELDS);
  15.     ZeroMem(anFieldLen, sizeof(int)*MAXNUMFIELDS);
  16.     ZeroMem(&nState, sizeof(nState));
  17.     lSrcLineNum = 0;
  18. }
  19.  
  20.  
  21.  
  22. CTag::~CTag(void)
  23. {
  24.     FreeText();
  25. }
  26.  
  27. void CTag::FreeText(void)
  28. {
  29.     int i;
  30.  
  31.     for(i = 0; i < nFields; i++)
  32.     {
  33.         if(aszFieldText[i])
  34.         {
  35.             delete aszFieldText[i];
  36.             aszFieldText[i] = NULL;
  37.         }
  38.     }
  39. }
  40.  
  41.  
  42. /**************************************************************************
  43.  Topic Class
  44.  **************************************************************************/
  45.  
  46. CTopic::CTopic(void)
  47. {
  48.     m_nWeight = 0;
  49.     m_lOffset = 0;
  50.     m_nDocTag = -1;
  51.     m_lSrcLineNum = 0;
  52.     m_nSrcFn = 0;
  53. }
  54.  
  55. CTopic::~CTopic(void)
  56. {
  57.     CTag *ptag;
  58.  
  59.     POSITION pos = m_listTags.GetHeadPosition();
  60.     while( pos )
  61.     {
  62.         ptag = m_listTags.GetNext(pos);
  63.         delete ptag;
  64.     }
  65. }
  66.  
  67.  
  68. void CTopic::FreeTagText(void)
  69. {
  70.     CTag *ptag;
  71.  
  72.     POSITION pos = m_listTags.GetHeadPosition();
  73.     while(pos)
  74.     {
  75.         ptag = m_listTags.GetNext(pos);
  76.         
  77.         ptag->FreeText();
  78.     }
  79. }
  80.  
  81. void CTopic::SetName(const char *sz)
  82. {
  83.     ASSERT(sz);
  84.  
  85.     m_sName = sz;
  86. }
  87.  
  88.  
  89. void CTopic::SetContext(const char *sz)
  90. {
  91.     ASSERT(sz);
  92.  
  93.     m_sCtx = sz;
  94. }
  95.  
  96.  
  97. void CTopic::SetWeight(int n)
  98. {
  99.     m_nWeight = n;
  100. }
  101.  
  102.  
  103. void CTopic::SetOffset(long l)
  104. {
  105.     m_lOffset = l;
  106. }
  107.  
  108.  
  109. void CTopic::SetTags(CTagList& listTags)
  110. {
  111.     POSITION pos = listTags.GetHeadPosition();
  112.     while( pos )
  113.         m_listTags.AddTail( listTags.GetNext(pos) );
  114. }
  115.  
  116.  
  117. const char *CTopic::GetName(void)
  118. {
  119.     return m_sName;
  120. }
  121.  
  122.  
  123. const char *CTopic::GetContext(void)
  124. {
  125.     return m_sCtx;
  126. }
  127.  
  128.  
  129.  
  130. int CTopic::CompareContext(CTopic &t)
  131. {
  132.     return _stricmp(m_sCtx, t.m_sCtx);
  133. }
  134.  
  135.  
  136. int CTopic::Compare(CTopic &t)
  137. {
  138.     if(m_nWeight < t.m_nWeight)
  139.         return -1;
  140.     else if(m_nWeight > t.m_nWeight)
  141.         return 1;
  142.  
  143.     return _stricmp(m_sName, t.m_sName);
  144. }
  145.  
  146.  
  147. CTag *CTopic::GetTopicTag(void)
  148. {
  149.     if(m_listTags.IsEmpty()) 
  150.         return NULL;
  151.     else 
  152.         return m_listTags.GetHead(); 
  153. }
  154.  
  155.  
  156. int CTopic::Write(CFile &f)
  157. {
  158. TRY
  159. {
  160.     if(m_listTags.GetCount() == 0)
  161.         return 0;
  162.     
  163.     m_lOffset = f.GetPosition();
  164.  
  165.     CTag *p;
  166.     int i;
  167.  
  168.     POSITION pos = m_listTags.GetHeadPosition();
  169.     while(pos)
  170.     {
  171.         p = m_listTags.GetNext( pos );
  172.  
  173.         for(i = 0; i < p->nFields; i++)
  174.         {
  175.             f.Write(p->aszFieldText[i], p->anFieldLen[i]);
  176.             
  177.             delete p->aszFieldText[i];
  178.  
  179.             p->aszFieldText[i] = NULL;
  180.         }
  181.     }
  182.  
  183.     return 0;
  184. }
  185. CATCH(CFileException, e)
  186. {
  187.     return e->m_cause;
  188. }
  189. END_CATCH
  190. }
  191.  
  192.  
  193.  
  194.  
  195. int CTopic::Read(CFile &f)
  196. {
  197. TRY
  198. {
  199.     if(!HasTags())
  200.         return 0;
  201.     
  202.     long lPos = f.Seek( m_lOffset, CFile::begin );
  203.     ASSERT(lPos == m_lOffset);
  204.  
  205.     CTag *  p;
  206.  
  207.     int     i;
  208.     POSITION pos = m_listTags.GetHeadPosition();
  209.     while( pos )
  210.     {
  211.         p = m_listTags.GetNext(pos);
  212.  
  213.         for(i = 0; i < p->nFields; i++)
  214.         {
  215.             p->aszFieldText[i] = new char[p->anFieldLen[i]+1];
  216.  
  217.             f.Read(p->aszFieldText[i], p->anFieldLen[i]);
  218.             p->aszFieldText[i][p->anFieldLen[i]] = '\0';
  219.         }
  220.     }
  221.  
  222.     return 0;
  223. }
  224. CATCH(CFileException, e)
  225. {
  226.     return e->m_cause;
  227. }
  228. END_CATCH
  229. }
  230.  
  231.  
  232. #ifdef _DEBUG
  233. void CTopic::Dump( CDumpContext &dc ) const
  234. {
  235.     dc << "CTopic "         << m_sName
  236.        << " ID: "           << m_sCtx
  237.        << " Source #: "     << m_nSrcFn 
  238.        << " Doc tags #: "     << m_nDocTag
  239.        << " Tags: \r\n";
  240.  
  241.     CTag *p;
  242.     int i;
  243.     POSITION pos = m_listTags.GetHeadPosition();
  244.     while(pos)
  245.     {
  246.         p = m_listTags.GetNext(pos);
  247.  
  248.         dc << "\t" << "Tag: " << p->sTag << " with "
  249.            << p->nFields << " fields;";
  250.  
  251.  
  252.         for(i = 0; i < p->nFields; i++)
  253.         {
  254.             dc << " " << p->anFieldLen[i];
  255.         }
  256.  
  257.         dc << "\r\n";
  258.     }
  259. }
  260. #endif
  261.  
  262. /**************************************************************************
  263.  Topic Log Class
  264.  **************************************************************************/
  265.  
  266. CTopicLog::CTopicLog(void)
  267. {
  268.     m_apTopicSort = NULL;
  269.     m_apTopicOutput = NULL;
  270.     m_nTopics = 0;
  271.     m_bIsSorted = NULL;
  272. }
  273.  
  274.  
  275. CTopicLog::~CTopicLog()
  276. {
  277.  
  278.     if(m_apTopicSort)
  279.         delete[] m_apTopicSort;
  280.  
  281.     CTopic *p;
  282.     CString s;
  283.     
  284.     POSITION pos = m_listTopics.GetHeadPosition();
  285.     while( pos != NULL)
  286.     {
  287.         p = m_listTopics.GetNext(pos);
  288.         delete p;
  289.     }
  290.  
  291.     m_listTopics.RemoveAll();
  292.  
  293.     int i, n;
  294.     for(i = 0, n = m_asDocTags.GetSize(); i < n; i++)
  295.         delete m_asDocTags[i];
  296.  
  297.     m_asDocTags.RemoveAll();
  298.  
  299.     for(i = 0, n = m_asSrcFn.GetSize(); i < n; i++)
  300.         delete m_asSrcFn[i];
  301.  
  302.     m_asSrcFn.RemoveAll();
  303. }
  304.  
  305.  
  306. void CTopicLog::Add(CTopic *pTopic, int nOptions)
  307. {
  308.     const char *szAddContext = pTopic->GetContext();
  309.     
  310.     POSITION pos = m_listTopics.GetHeadPosition();
  311.     POSITION posCur;
  312.     CTopic *p, *pMatch = NULL;
  313.     
  314.     while( pos != NULL)
  315.     {
  316.         posCur = pos;
  317.         p = m_listTopics.GetNext( pos );
  318.  
  319.         if(strcmp(p->GetContext(), szAddContext) == 0)
  320.         {
  321.             pMatch = p;
  322.             break;
  323.         }
  324.     }
  325.  
  326.     // If overwriting empty, delete any matching item
  327.     // and add the new one to the end.
  328.  
  329.     if(((nOptions & AddOverwrite) && pMatch) ||
  330.        ((nOptions & AddGenerateUnique) && pMatch && !pMatch->HasTags()))
  331.     {
  332.         m_listTopics.RemoveAt(posCur);
  333.         delete pMatch;
  334.     }
  335.  
  336.     // If generating unique, and we find a match, take
  337.     // a walk through the topic list and keep looking
  338.     // for dupes until we have a unique context string.
  339.  
  340.     else if((nOptions & AddGenerateUnique) && pMatch)
  341.     {
  342.         CString sNewContext;
  343.         CTopic *pNext;
  344.         char szNum[10];
  345.         int n = 1;
  346.         do
  347.         {
  348.             sprintf(szNum, "_%d", n);
  349.             sNewContext = szAddContext;
  350.             sNewContext += szNum;
  351.             pMatch = NULL;
  352.             while( pos )
  353.             {
  354.                 pNext = m_listTopics.GetNext( pos );
  355.                 if(sNewContext.Compare(pNext->GetContext()) == 0)
  356.                 {
  357.                     pMatch = pNext;
  358.                     break;
  359.                 }
  360.             }
  361.             n++;
  362.  
  363.         } while(pMatch);
  364.         
  365.         pTopic->SetContext(sNewContext);
  366.     }
  367.  
  368.     // Add the topic
  369.  
  370.     m_listTopics.AddTail(pTopic);
  371. }
  372.  
  373.  
  374. BOOL CTopicLog::Search(const char *szID, CTopic *&p)
  375. {
  376.     ASSERT(m_apTopicSort);
  377.         
  378.     p = NULL;
  379.  
  380.     int iFirst, iLast, i, nRet;
  381.  
  382.     iFirst = 0;
  383.     iLast = m_listTopics.GetCount()-1;
  384.     while(iFirst <= iLast)
  385.     {
  386.         i = (iFirst + iLast) / 2;
  387.  
  388.         ASSERT(m_apTopicSort[i]);
  389.  
  390.         nRet = _stricmp(szID, m_apTopicSort[i]->GetContext());
  391.  
  392.         if(nRet > 0)
  393.         {
  394.             iFirst = i+1;
  395.         }
  396.         else if(nRet < 0)
  397.         {
  398.             iLast = i-1;
  399.         }
  400.         else
  401.         {
  402.             p = m_apTopicSort[i];
  403.             return TRUE;
  404.         }
  405.     }
  406.     
  407.     return FALSE;
  408. }
  409.  
  410.  
  411. int CompareLogsWeighted(const void *elem1, const void *elem2)
  412. {
  413.     CTopic *p1, *p2;
  414.  
  415.     p1 = *(CTopic **)elem1;
  416.     p2 = *(CTopic **)elem2;
  417.  
  418.     ASSERT(p1 && p2);
  419.  
  420.     return p1->Compare(*p2);
  421. }
  422.  
  423. int CompareLogs(const void * elem1, const void * elem2)
  424. {
  425.     CTopic *p1, *p2;
  426.  
  427.     p1 = *(CTopic **)elem1;
  428.     p2 = *(CTopic **)elem2;
  429.  
  430.     ASSERT(p1 && p2);
  431.  
  432.     return p1->CompareContext(*p2);
  433. }
  434.  
  435. void CTopicLog::Sort(BOOL bOutputSorted)
  436. {
  437.     if(m_apTopicSort)
  438.     {
  439.         delete[] m_apTopicSort;
  440.         delete[] m_apTopicOutput;
  441.     }
  442.  
  443.     m_apTopicSort = new CTopic*[GetLogCount()];
  444.     m_apTopicOutput = new CTopic*[GetLogCount()];
  445.  
  446.     CTopic *pTopic;
  447.     UINT nLogTopics;
  448.     CString s;
  449.  
  450.     nLogTopics = 0;
  451.     m_nTopics = 0;
  452.     POSITION pos = m_listTopics.GetHeadPosition();
  453.  
  454.     while(pos)
  455.     {
  456.         pTopic = m_listTopics.GetNext( pos );
  457.  
  458.         m_apTopicSort[nLogTopics++] = pTopic;
  459.  
  460.         if(pTopic->HasTags())
  461.             m_apTopicOutput[m_nTopics++] = pTopic;
  462.     }
  463.  
  464.     m_bIsSorted = FALSE;
  465.         
  466.     qsort(m_apTopicSort, nLogTopics, sizeof(CTopic *), 
  467.             CompareLogs);
  468.  
  469.     if(bOutputSorted)
  470.     {
  471.         qsort(m_apTopicOutput, m_nTopics, sizeof(CTopic *), 
  472.             CompareLogsWeighted);
  473.     }
  474.  
  475.     m_bIsSorted = TRUE;
  476. }
  477.  
  478.  
  479. CTopic *CTopicLog::GetTopicSortOrder(UINT i)
  480. {
  481.     ASSERT(m_apTopicSort);
  482.     ASSERT(i >= 0 && i < m_nTopics);
  483.  
  484.     if(i >= 0 && i < m_nTopics)
  485.         return m_apTopicSort[i];
  486.  
  487.     return NULL;
  488. }
  489.  
  490.  
  491. CTopic *CTopicLog::GetTopicOutputOrder(UINT i)
  492. {
  493.     ASSERT(m_apTopicOutput);
  494.     ASSERT(i >= 0 && i < m_nTopics);
  495.  
  496.     if(i >= 0 && i < m_nTopics)
  497.         return m_apTopicOutput[i];
  498.  
  499.     return NULL;
  500. }
  501.  
  502.  
  503.  
  504. #ifdef _DEBUG
  505. void CTopicLog::Dump( CDumpContext &dc ) const
  506. {
  507.     POSITION pos = m_listTopics.GetHeadPosition();
  508.  
  509.     dc << "CTopicLog: " << m_listTopics.GetCount() 
  510.        << " topics.\r\n";
  511.  
  512.     CString s;
  513.     CObject *p;
  514.     while(pos != NULL)
  515.     {
  516.         p = m_listTopics.GetNext( pos );
  517.  
  518.         dc << *p;   
  519.     }
  520. }
  521. #endif
  522.  
  523.  
  524.  
  525. int CTopicLog::Print(
  526.     const char *szFile,         // @parm File to print to.
  527.     int  bConcat)               // @parm Whether to concatenate
  528. {
  529. TRY
  530. {
  531.     CFile file;
  532.     CFileException e;
  533.     CFileStatus r;
  534.     const char *sz;
  535.  
  536.     int nOpenFlags;
  537.  
  538.     if(bConcat & file.GetStatus(szFile, r))
  539.         nOpenFlags = CFile::modeReadWrite;
  540.     else
  541.         nOpenFlags = CFile::modeCreate | CFile::modeWrite;
  542.  
  543.     if(!file.Open(szFile, nOpenFlags, &e))
  544.         return e.m_cause;
  545.  
  546.     if(bConcat)
  547.         file.SeekToEnd();
  548.  
  549.     CTopic *pTopic;
  550.     CString s;
  551.     UINT nTopics = GetLogCount();
  552.  
  553.     for(UINT i = 0; i < nTopics; i++)
  554.     {
  555.         pTopic = m_apTopicSort[i];
  556.  
  557.         if(pTopic->HasTags())
  558.         {
  559.             sz = pTopic->GetContext();
  560.             file.Write(sz, strlen(sz));
  561.             file.Write("\r\n", 2);
  562.         }
  563.     }
  564.  
  565.     file.Close();
  566.  
  567.     return 0;
  568. }
  569. CATCH(CFileException, e)
  570. {
  571.     return e->m_cause;
  572. }
  573. END_CATCH
  574. }
  575.  
  576.  
  577.  
  578. int CTopicLog::AddSrcFn(const char *szInput)
  579. {
  580.     CString *psNew = new CString(szInput);
  581.  
  582.     int n = m_asSrcFn.GetSize();
  583.  
  584.     m_asSrcFn.SetSize(n+1);
  585.     m_asSrcFn[n] = psNew;
  586.  
  587.     return n;
  588. }
  589.  
  590. const char *CTopicLog::GetSrcFn(int n)
  591. {
  592.     if(-1 == n)
  593.     {
  594.         n = m_asSrcFn.GetUpperBound();
  595.     }
  596.  
  597.     ASSERT(n >= 0 && n < m_asSrcFn.GetSize());
  598.  
  599.     return *m_asSrcFn[n];
  600. }
  601.  
  602. int CTopicLog::AddDocTag(const char *szInput)
  603. {
  604.     CString *psNew = new CString(szInput);
  605.  
  606.     int n = m_asDocTags.GetSize();
  607.  
  608.     m_asDocTags.SetSize(n+1);
  609.     m_asDocTags[n] = psNew;
  610.  
  611.     return n;
  612. }
  613.  
  614. const char *CTopicLog::GetDocTag(int n)
  615. {
  616.     if(-1 == n)
  617.     {
  618.         n = m_asDocTags.GetUpperBound();
  619.     }
  620.  
  621.     ASSERT(n >= 0 && n < m_asDocTags.GetSize());
  622.  
  623.     return *m_asDocTags[n];
  624. }
  625.  
  626.